﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace iWare.Wms.Application
{
    /// <summary>
    /// 仓库字典类型服务
    /// </summary>
    [Route("api/WareDicType")]
    [ApiDescriptionSettings("仓库基础数据", Name = "DicType", Order = 199)]

    public class WareDicTypeService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WareDicType, MasterDbContextLocator> _wareDicTypeRep; //仓库字典类型仓储
        private readonly WareDictDataService _wareDictDataService; //仓库字典值仓储

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareDicTypeRep"></param>
        /// <param name="wareDictDataService"></param>
        public WareDicTypeService(
            IRepository<WareDicType, MasterDbContextLocator> wareDicTypeRep,
            WareDictDataService wareDictDataService
        )
        {
            _wareDicTypeRep = wareDicTypeRep;
            _wareDictDataService = wareDictDataService;
        }
        #endregion

        /// <summary>
        /// 分页查询字典类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("page")]
        public async Task<PageResult<WareDicType>> Page([FromQuery] WareDicTypeSearch input)
        {
            bool supperAdmin = CurrentUserInfo.IsSuperAdmin;

            return await _wareDicTypeRep.DetachedEntities
                .Where(u => u.Status != CommonStatus.DELETED && !supperAdmin || u.Status <= CommonStatus.DELETED && supperAdmin).OrderBy(u => u.Sort)
                .Where(!string.IsNullOrEmpty(input.Code), u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.Name), u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%"))
                .ToADPagedListAsync(input.PageNo, input.PageSize);
        }

        /// <summary>
        /// 获取字典类型列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("list")]
        public async Task<List<WareDicType>> List()
        {
            return await _wareDicTypeRep.DetachedEntities.Where(u => u.Status != CommonStatus.DELETED).ToListAsync();
        }

        /// <summary>
        /// 获取字典类型下所有字典值
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("dropDown")]
        public async Task<List<WareDictData>> GetWareDicTypeDropDown([FromQuery] DropDownWareDicTypeInput input)
        {
            var wareDictTypes = await _wareDicTypeRep.FirstOrDefaultAsync(u => u.Code == input.Code, false);
            if (wareDictTypes == null) throw Oops.Oh(ErrorCode.D3000);
            return await _wareDictDataService.GetDictDataListByDictTypeId(wareDictTypes.Id);
        }

        /// <summary>
        /// 新增字典类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("add")]
        public async Task Add(AddWareDicTypeInput input)
        {
            var isExist = await _wareDicTypeRep.AnyAsync(u => u.Name == input.Name || u.Code == input.Code, false);
            if (isExist) throw Oops.Oh(ErrorCode.D3001);

            var wareDictTypes = input.Adapt<WareDicType>();
            await _wareDicTypeRep.InsertAsync(wareDictTypes);
        }

        /// <summary>
        /// 删除字典类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("delete")]
        public async Task Delete(DeleteWareDicTypeInput input)
        {
            var wareDictTypes = await _wareDicTypeRep.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (wareDictTypes == null) throw Oops.Oh(ErrorCode.D3000);

            if (wareDictTypes.Status == CommonStatus.DELETED)
            {
                await wareDictTypes.DeleteAsync();
            }
            else
            {
                wareDictTypes.Status = CommonStatus.DELETED;
                wareDictTypes.IsDeleted = true;
            }
        }

        /// <summary>
        /// 更新字典类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("edit"),]
        public async Task Update(UpdateWareDicTypeInput input)
        {
            var isExist = await _wareDicTypeRep.AnyAsync(u => u.Id == input.Id, false);
            if (!isExist) throw Oops.Oh(ErrorCode.D3000);

            // 排除自己并且判断与其他是否相同
            isExist = await _wareDicTypeRep.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id, false);
            if (isExist) throw Oops.Oh(ErrorCode.D3001);

            var wareDictTypes = input.Adapt<WareDicType>();
            await _wareDicTypeRep.UpdateAsync(wareDictTypes, ignoreNullValues: true);
        }

        /// <summary>
        /// 字典类型详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("detail")]
        public async Task<WareDicType> Get([FromQuery] QueryWareDicTypeInfoInput input)
        {
            return await _wareDicTypeRep.FirstOrDefaultAsync(u => u.Id == input.Id, false);
        }

        /// <summary>
        /// 更新字典类型状态
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("changeStatus")]
        public async Task ChangeStatus(ChangeStateWareDicTypeInput input)
        {
            var dictType = await _wareDicTypeRep.FirstOrDefaultAsync(u => u.Id == input.Id);
            if (dictType == null) throw Oops.Oh(ErrorCode.D3000);

            if (!Enum.IsDefined(typeof(CommonStatus), input.Status))
                throw Oops.Oh(ErrorCode.D3005);

            dictType.Status = input.Status;
            dictType.IsDeleted = false;
        }

        /// <summary>
        /// 字典类型与字典值构造的字典树
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("tree")]
        public async Task<List<WareDictTreeOutput>> GetWareDicTree()
        {
            return await _wareDicTypeRep.DetachedEntities.Select(u => new WareDictTreeOutput
            {
                Id = u.Id,
                Code = u.Code,
                Name = u.Name,
                Children = u.WareDictDatas.Select(c => new WareDictTreeOutput
                {
                    Id = c.Id,
                    Pid = c.TypeId,
                    Code = c.Code,
                    Name = c.Value
                }).ToList()
            }).ToListAsync();
        }
    }
}
